home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / jovept1.arc / DISP.C < prev    next >
Text File  |  1985-05-30  |  19KB  |  820 lines

  1. /* disp.c */
  2.  
  3. /* JOVE/MSDOS. K. Mitchum 1/85 */
  4. /* Modifications for personal use only. */
  5. /* original code J. Payne LSRHS 5/83 */
  6. /* Ken Mitchum */
  7. /* University of Pittsburgh */
  8. /* Decision Systems Laboratory */
  9.  
  10.  
  11. /* Jonathan Payne at Lincoln-Sudbury Regional High School 5-25-83
  12.  
  13.    jove_disp.c
  14.  
  15.    This code figures out the best way to update the screen.
  16.    It contains the procedure "redisplay()" that should be called
  17.    whenever the screen needs updating.  This optimizes interline
  18.    movement and intraline movement, taking advantage of insert/delete
  19.    line/character features of the terminal (if they exist).  */
  20.  
  21. #include "jove.h"
  22. #include "term.h"
  23. #include "screen.h"
  24.  
  25. #ifdef UNIX
  26. #include <signal.h>
  27. #else
  28. #include "signal.h"
  29. #endif
  30.  
  31. #define    TOPGONE    01
  32. #define    CURGONE    02    /* Topline (curline) of window has been deleted
  33.                since the last time a redisplay was called. */
  34.  
  35. extern int errormsg;    /* main.c */
  36. extern int ScrollStep;
  37. extern char    mesgbuf[];
  38. extern char    *cursend;
  39. extern SCRLNE    *Screen;
  40. extern SCRLNE    *Curline;
  41.  
  42.  
  43. int    UpdModLine = 0;
  44.  
  45.  
  46. int    UpdWCalls,    /* Number of times we called UpdateWindow for this window */
  47.     IDstart,    /* First different line */
  48.     NumDirty;    /* Number of dirty lines in this screen update */
  49.  
  50.  
  51. static struct scrimage    dirty_plate = { 0, DIRTY, 0, 0 };
  52. static struct scrimage    clean_plate = { 0, 0, 0, 0 };
  53.  
  54. /* Kludge windows gets called by the routines that delete lines from the
  55.    buffer.  If the w->w_line or w->w_top are deleted and this procedure
  56.    is not called, the redisplay routine will barf. */
  57.  
  58. KludgeWindows(line1, line2)
  59. LINE    *line1;
  60. register LINE    *line2;
  61. {
  62.     register WINDOW    *w = fwind;
  63.     register LINE    *lp;
  64.  
  65.     do {
  66.         for (lp = line1->l_next; lp != line2->l_next; lp = lp->l_next) {
  67.             if (lp == w->w_top)
  68.                 w->w_flags |= TOPGONE;
  69.             if (lp == w->w_line)
  70.                 w->w_flags |= CURGONE;
  71.         }
  72.         w = w->w_next;
  73.     } while (w != fwind);
  74. }
  75.  
  76. inlist(first, what)
  77. register LINE    *first,
  78.         *what;
  79. {
  80.     while (first) {
  81.         if (first == what)
  82.             return 1;
  83.         first = first->l_next;
  84.     }
  85.     return 0;
  86. }
  87.  
  88.  
  89.  
  90.  
  91. /* The redisplay algorithm:
  92.  
  93.    Jove remembers where each buffer lines is on the screen in the array
  94.    `oimage' (old image).  UpdateWindow() makes a new image, in `nimage',
  95.    by started from w->w_top and working to the bottom line of the window.
  96.    A line by line comparison starts from nimage[0] and oimage[0], and if
  97.    there are no differences, no insert/delete lines is done.  When there
  98.    is a difference, there are two possibilities:
  99.  
  100.     Some lines were deleted in the buffer.  This is detected by looking
  101.      further down in the old image, for the line where the difference occurred
  102.      in the new image.  So where we used to have 1-2-3-4 (oimage), we now have
  103.      1-4, in which case two lines were deleted.
  104.  
  105.         Some lines were inserted in the buffer.  This is detected by looking
  106.      further down in the new image, for the line where the difference occurred
  107.      in the old image.  So where we used to have 1-2-3, we now have 1-2-4-5-3,
  108.      in which case two lines were inserted (lines 4 and 5).
  109.  
  110.    UpdateWindow has a few optimizations in it, e.g. it checks for
  111.    mismatches AS it builds `nimage', and sets a variable to the line number
  112.    at which the difference occurred.  It also keeps a count of the number
  113.    of lines that need updating i.e. the line was changed by an editing
  114.    operation, or the start print column is different (the line just scrolled
  115.    left or right).  Imagine that a single character was inserted on the top
  116.    line of the screen.  The number of lines that are dirty = 1, so the loop
  117.    that checks to see that all the lines are up-to-date can terminate after
  118.    updating the first line WITHOUT checking the rest of the lines. */
  119.  
  120. redisplay()
  121. {
  122.     register WINDOW    *w = fwind;
  123.     int    lineno,
  124.         i;
  125.     register struct scrimage    *np,
  126.                     *op;
  127.  
  128.     curwind->w_bufp = curbuf;
  129.     if (curwind->w_line != curline)
  130.         curwind->w_offset = 0;
  131.     curwind->w_line = curline;
  132.     curwind->w_char = curchar;
  133.  
  134.     if (InputPending = charp())
  135.         return;
  136.     if (RingBell) sendbell();
  137.  
  138.     /* So messages that aren't error messages don't hang around forever */
  139.     if (!UpdMesg && !Asking) {    /* Don't erase if we are asking */
  140.         if (mesgbuf[0] && !errormsg)
  141.             message("");
  142.     }
  143.     if (UpdMesg)
  144.         UpdateMesg();
  145.  
  146.     NumDirty = 0;
  147.     IDstart = -1;
  148.  
  149.     for (lineno = 0, w = fwind; lineno < LI - 1; w = w->w_next) {
  150.         UpdWCalls = 0;
  151.         UpdateWindow(w, lineno);
  152.         lineno += w->w_height;
  153.     }
  154.  
  155.     if (IDstart != -1) {        /* Shucks this is gonna be slower */
  156.         DoIDline(IDstart);
  157.         NumDirty = LI - 1;
  158.     }
  159.  
  160.     np = nimage;
  161.     op = oimage;
  162.     for (i = 0; i < LI - 1 && NumDirty > 0; i++, np++, op++) {
  163.         if ((np->Sflags & DIRTY) ||
  164.                 op->Line != np->Line ||
  165.                 op->StartCol != np->StartCol ||
  166.                 (UpdModLine && np->Sflags & MODELINE)) {
  167.             UpdateLine(np->Window, i);
  168.             NumDirty--;
  169.         }
  170.         if (InputPending)
  171.             return;
  172.     }
  173.     UpdModLine = 0;
  174.  
  175.     if (InputPending)
  176.         return;
  177.     if (Asking) {
  178.         Placur(LI - 1, calc_pos(mesgbuf, Asking));
  179.             /* Nice kludge */
  180.         flusho();
  181.     } else
  182.         GotoDot();
  183. }
  184.  
  185.  
  186. DoIDline(start)
  187. {
  188.     register struct scrimage    *np = nimage,
  189.                     *op = oimage;
  190.     register int    i;
  191.     int    j;
  192.  
  193.     /* Some changes have been made.  Try for insert or delete lines.
  194.        If either case has happened, Addlines and/or DeltLines will do
  195.        necessary scrolling, also CONVERTING oimage to account for the
  196.        physical changes.  The comparison continues from where the
  197.        insertion/deletion takes place; this doesn't happen very often,
  198.        usually it happens with more than one window with the same
  199.        buffer. */
  200.  
  201.     if (!CanScroll)
  202.         return;        /* We should never have been called! */
  203.  
  204.     for (i = start; i < LI - 1; i++) {
  205.         for (j = i + 1; j < LI - 1; j++) {
  206.             if (np[j].Line != 0 && np[j].Line == op[j].Line)
  207.                 break;
  208.             if (np[j].Line == op[i].Line) {
  209.                 if (np[j].Line == 0)
  210.                     continue;
  211.                 if (AddLines(i, j - i)) {
  212.                     DoIDline(j);
  213.                     return;
  214.                 }
  215.                 break;
  216.             }
  217.             if (np[i].Line == op[j].Line) {
  218.                 if (np[i].Line == 0)
  219.                     continue;
  220.                 if (DeltLines(i, j - i)) {
  221.                     DoIDline(i);
  222.                     return;
  223.                 }
  224.                 break;
  225.             }
  226.         }
  227.     }
  228. }
  229.  
  230. /* Make nimage reflect what the screen should look like when we are done
  231.    with the redisplay.  This deals with horizontal scrolling.  Also makes
  232.    sure the current line of the window is in the window. */
  233.  
  234. UpdateWindow(w, start)
  235. register WINDOW    *w;
  236. {
  237.     LINE    *lp;
  238.     int    i,
  239.         DotIsHere = 0,
  240.         upper,        /* Top of window */
  241.         lower;        /* Bottom of window */
  242.     register struct scrimage    *np,
  243.                     *op;
  244.     int    savestart = IDstart;
  245.  
  246.     if (w->w_flags & CURGONE) {
  247.         w->w_line = w->w_bufp->b_dot;
  248.         w->w_char = w->w_bufp->b_char;
  249.     }
  250.     if (w->w_flags & TOPGONE)
  251.         CalcTop(w);    /* Reset topline of screen */
  252.     w->w_flags = 0;
  253.  
  254.     upper = start;
  255.     lower = upper + w->w_height - 1;    /* Don't include modeline */
  256.     np = &nimage[upper];
  257.     op = &oimage[upper];
  258.     for (i = upper, lp = w->w_top; lp != 0 && i < lower;
  259.                     i++, np++, op++, lp = lp->l_next) {
  260.         if (lp == w->w_line) {
  261.             w->w_dotcol = find_pos(lp, w->w_char);
  262.             w->w_dotline = i;
  263.  
  264.             if (w->w_numlines)
  265.                 w->w_dotcol += 8;
  266.             DotIsHere++;
  267.             if (w->w_dotcol < np->StartCol ||
  268.                 (w->w_dotcol + 2) >= (np->StartCol + CO)) {
  269.                 if (w->w_dotcol + 2 < CO)
  270.                     w->w_offset = 0;
  271.                 else
  272.                     w->w_offset = w->w_dotcol - (CO / 2);
  273.             }
  274.             np->StartCol = w->w_offset;
  275.         } else
  276.             np->StartCol = 0;
  277.  
  278.         if ((np->Sflags = (lp->l_dline & DIRTY)) ||
  279.                     np->StartCol != op->StartCol)
  280.             NumDirty++;
  281.         if (((np->Line = lp) != op->Line) && IDstart == -1)
  282.             IDstart = i;
  283.         np->Window = w;
  284.     }
  285.     if (!DotIsHere) {    /* Current line not in window */
  286.         if (UpdWCalls != 0) {
  287.             printf("\rCalled UpdateWindow too many times");
  288.             finish(SIGHUP);
  289.         }
  290.         IDstart = savestart;
  291.         UpdWCalls++;
  292.         CalcScroll(w);
  293.         UpdateWindow(w, start);    /* This time for sure */
  294.         return;
  295.     }
  296.  
  297.     /* Is structure assignment faster than copy each field seperately */
  298.     if (i < lower) {
  299.  
  300.         for (; i < lower; i++, np++, op++) {
  301.             if (np->Sflags = ((op->Line) ? DIRTY : 0)) {
  302.                 NumDirty++;
  303. #ifdef UNIX
  304.                 *np = dirty_plate;
  305. #else
  306. /*            np->StartCol = dirty_plate.StartCol;
  307.             np->Sflags = dirty_plate.Sflags;
  308.             np->Line = dirty_plate.Line;
  309.             np->Window = dirty_plate.Window;
  310. */
  311.             movmem(&dirty_plate,np,sizeof(struct scrimage));
  312. #endif
  313.             } else
  314. #ifdef UNIX
  315.                 *np = clean_plate;
  316. #else
  317. /*            np->StartCol = clean_plate.StartCol;
  318.             np->Sflags = clean_plate.Sflags;
  319.             np->Line = clean_plate.Line;
  320.             np->Window = clean_plate.Window;
  321. */
  322.             movmem(&clean_plate,np,sizeof(struct scrimage));
  323. #endif
  324.         }
  325.     }
  326.         
  327.     if (((np->Line = (LINE *) w->w_bufp) != op->Line) || UpdModLine) {
  328.         if (IDstart == -1)
  329.             IDstart = i;
  330.         NumDirty++;
  331.     }
  332.  
  333.     np->Sflags = MODELINE;
  334.     np->Window = w;
  335. }
  336.  
  337. /* Make `buf' modified and tell the redisplay code to update the modeline
  338.    if it will need to be changed. */
  339.  
  340. SetModified(buf)
  341. BUFFER    *buf;
  342. {
  343.     extern int    DOLsave;
  344.  
  345.     if (!buf->b_modified)
  346.         UpdModLine++;
  347.     buf->b_modified = 1;
  348.     DOLsave++;
  349. }
  350.  
  351. SetUnmodified(buf)
  352. BUFFER    *buf;
  353. {
  354.     if (buf->b_modified)
  355.         UpdModLine++;
  356.     buf->b_modified = 0;
  357. }
  358.  
  359. /* Write whatever is in mesgbuf (maybe we are Asking,  or just printed
  360.    a message.  Turns off the Update Mesg line flag */
  361.  
  362. UpdateMesg()
  363. {
  364.     i_set(LI - 1, 0);
  365.     if (swrite(mesgbuf,0)) {
  366.         cl_eol();
  367.         UpdMesg = 0;
  368.     }
  369.     flusho();
  370. }
  371.  
  372. /* Goto the current position in the current window.  Presumably redisplay()
  373.    has already been called, and curwind->{w_dotline,w_dotcol} have been set
  374.    correctly. */
  375.  
  376. GotoDot()
  377. {
  378.     if (InputPending)
  379.         return;
  380.     Placur(curwind->w_dotline, curwind->w_dotcol -
  381.                 oimage[curwind->w_dotline].StartCol);
  382.     flusho();
  383. }
  384.  
  385. /* Put the current line of `w' in the middle of the window */
  386.  
  387. CalcTop(w)
  388. WINDOW    *w;
  389. {
  390.     SetTop(w, prev_line(w->w_line, HALF(w)));
  391. }
  392.  
  393.  
  394.  
  395. /* Calculate the new topline of the screen; different when in single-scroll
  396.    mode */
  397.  
  398. CalcScroll(w)
  399. register WINDOW    *w;
  400. {
  401.     extern int    diffnum;
  402.     register int    up;
  403.  
  404.     if (ScrollStep == 0)    /* Means just center it */
  405.         CalcTop(w);
  406.     else {
  407.         up = inorder(w->w_line, 0, w->w_top, 0);
  408.         if (up)        /* Dot is above the screen */
  409.             SetTop(w, prev_line(w->w_line, min(ScrollStep - 1, HALF(w))));
  410.         else
  411.             SetTop(w, prev_line(w->w_line,
  412.                     (SIZE(w) - 1) -
  413.                     min(ScrollStep - 1, HALF(w))));
  414.     }
  415. }
  416.  
  417. UntilEqual(start)
  418. register int    start;
  419. {
  420.     register struct scrimage    *np = &nimage[start],
  421.                     *op = &oimage[start];
  422.  
  423.     while ((start < LI - 1) && (np->Line != op->Line)) {
  424.         np++;
  425.         op++;
  426.         start++;
  427.     }
  428.  
  429.     return start;
  430. }
  431.  
  432. /* Calls the routine to do the physical changes, and changes oimage to
  433.    reflect those changes. */
  434.  
  435. AddLines(at, num)
  436. register int    at,
  437.         num;
  438. {
  439.     register  int    i;
  440.     int    bottom = UntilEqual(at + num);
  441.  
  442.     if (num == 0 || num >= ((bottom - 1) - at))
  443.         return 0;    /* We did nothing */
  444.     v_ins_line(num, at, bottom - 1);
  445.  
  446.     /* Now change oimage to account for the physical change */
  447. #ifdef UNIX
  448.     for (i = bottom - 1; i - num >= at; i--) {    /***/
  449.  
  450.         oimage[i] = oimage[i - num];
  451.  
  452. /*        oimage[i].StartCol = oimage[i-num].StartCol;
  453.         oimage[i].Sflags = oimage[i-num].Sflags;
  454.         oimage[i].Line = oimage[i-num].Line;
  455.         oimage[i].Window = oimage[i-num].Window;
  456. */
  457. /*        movmem(oimage+i-num,oimage+i,sizeof(struct scrimage)); */
  458.     }
  459. #else
  460.         i = bottom -at -num;
  461.         movmem(oimage+at,oimage+at+num, i * sizeof(struct scrimage));
  462. #endif
  463.  
  464.     for (i = 0; i < num; i++)
  465.         oimage[at + i].Line = 0;
  466.     return 1;    /* We did something */
  467. }
  468.  
  469. DeltLines(at, num)
  470. register int    at,
  471.         num;
  472. {
  473.     register int    i;
  474.     int    bottom = UntilEqual(at + num);
  475.  
  476.     if (num == 0 || num >= ((bottom - 1) - at))
  477.         return 0;
  478.     v_del_line(num, at, bottom - 1);
  479.  
  480. #ifdef UNIX
  481.     for (i = at; num + i < bottom; i++) {
  482.  
  483.         oimage[i] = oimage[num + i];    /****/
  484.  
  485. /*        oimage[i].StartCol = oimage[i+num].StartCol;
  486.         oimage[i].Sflags = oimage[i+num].Sflags;
  487.         oimage[i].Line = oimage[i+num].Line;
  488.         oimage[i].Window = oimage[i+num].Window;
  489. */
  490. /*        movmem(oimage+i+num,oimage+i,sizeof(struct scrimage)); */
  491.  
  492.     }
  493. #else
  494.         i = bottom - at - num;
  495.         movmem(oimage+at+num,oimage+at, i * sizeof(struct scrimage));
  496. #endif
  497.  
  498.     for (i = bottom - num; i < bottom; i++)
  499.         oimage[i].Line = 0;
  500.     return 1;
  501. }
  502.  
  503. DeTab(StartCol, buf, outbuf, limit)
  504. register char    *buf;
  505. char    *outbuf;
  506. {
  507.     register char    *op = outbuf,
  508.             c;
  509.     register int    pos = 0;
  510.  
  511. #define OkayOut(ch)    if ((pos++ >= StartCol) && (op < &outbuf[limit]))\
  512.                 *op++ = ch;\
  513.             else
  514.  
  515.     while (c = *buf++) {
  516.         if (c == '\t') {
  517.             int    nchars = (tabstop - (pos % tabstop));
  518.  
  519.             while (nchars--)
  520.                 OkayOut(' ');
  521.  
  522.         } else if (c < ' ' || c == 0177) {
  523.             OkayOut('^');
  524.             OkayOut(c == 0177 ? '?' : c + '@');
  525.         } else
  526.             OkayOut(c);
  527.         if (pos - StartCol >= CO) {
  528.             op = &outbuf[CO - 1];
  529.             *op++ = '!';
  530.             break;
  531.         }            
  532.     }
  533.     *op = 0;
  534. }
  535.  
  536. /* Update line linenum in window w.  Only set oimage to nimage if
  537.  * the swrite or cl_eol works, that is nothing is interupted by 
  538.  * characters typed
  539.  */
  540.  
  541. UpdateLine(w, linenum)
  542. register WINDOW    *w;
  543. register int    linenum;
  544. {
  545.  
  546.     register struct scrimage    *np = &nimage[linenum];
  547.  
  548.     if (np->Sflags == MODELINE)
  549.         ModeLine(w);
  550.     else if (np->Line) {
  551.         np->Line->l_dline &= ~DIRTY;
  552.         np->Sflags &= ~DIRTY;
  553.         i_set(linenum, 0);
  554.         if (!hasIC && w->w_numlines)
  555.             ignore(swrite(sprint("%6d  ", (linenum - FLine(w) +
  556.                     w->w_topnum)),0));
  557.         if (hasIC) {
  558.             char    outbuf[132],
  559.                 buff[LBSIZE],
  560.                 *bptr;
  561.             int    fromcol = w->w_numlines ? 8 : 0;
  562.  
  563.             if (w->w_numlines) {
  564.                 ignore(sprintf(buff, "%6d  ", (linenum - FLine(w) +
  565.                         w->w_topnum)));
  566.                 ignore(getcptr(np->Line, buff + fromcol));
  567.                 bptr = buff;
  568.             } else
  569.                 bptr = getcptr(np->Line, buff);
  570.             DeTab(np->StartCol, bptr,
  571.                 outbuf, (sizeof outbuf) - 1);
  572.             if (!IDchar(outbuf, linenum, 0)) {
  573. #ifdef UNIX
  574.                 oimage[linenum] = *np;    /***/
  575. #else
  576. /*        oimage[linenum].StartCol = np->StartCol;
  577.         oimage[linenum].Sflags = np->Sflags;
  578.         oimage[linenum].Line = np->Line;
  579.         oimage[linenum].Window = np->Window;
  580. */
  581.         movmem(np,oimage+linenum,sizeof(struct scrimage));
  582. #endif
  583.         }    else if (i_set(linenum, 0), swrite(outbuf,0))
  584.                 do_cl_eol(linenum);
  585.             else
  586.                 oimage[linenum].Line = (LINE *) -1;
  587.         } else if (BufSwrite(linenum))
  588.             do_cl_eol(linenum);
  589.         else
  590.             oimage[linenum].Line = (LINE *) -1;
  591.     } else if (oimage[linenum].Line) {    /* Not the same ... make sure */
  592.         i_set(linenum, 0);
  593.         do_cl_eol(linenum);
  594.     }
  595. }
  596.  
  597. do_cl_eol(linenum)
  598. register int    linenum;
  599. {
  600.     cl_eol();
  601. #ifdef UNIX
  602.     oimage[linenum] = nimage[linenum];    /***/
  603. #else
  604. /*        oimage[linenum].StartCol = nimage[linenum].StartCol;
  605.         oimage[linenum].Sflags = nimage[linenum].Sflags;
  606.         oimage[linenum].Line = nimage[linenum].Line;
  607.         oimage[linenum].Window = nimage[linenum].Window;
  608. */
  609.         movmem(nimage+linenum,oimage+linenum,sizeof(struct scrimage));
  610. #endif
  611. }
  612.  
  613.  
  614. int    InMode = 0;
  615.  
  616. CopyTo(to, from, limit)
  617. register char    *to,
  618.         *from,
  619.         *limit;
  620. {
  621.     while (from <= limit)
  622.         *to++ = *from++;
  623. }
  624.  
  625. /* ID character routines full of special cases and other fun stuff like that.
  626.    It actually works thougth ... */
  627.  
  628. IDchar(new, lineno, col)
  629. register char    *new;
  630. {
  631.     int    i,
  632.         j,
  633.         oldlen,
  634.         NumSaved;
  635.     register SCRLNE    *sline = &Screen[lineno];
  636.  
  637.     oldlen = sline->s_length - sline->s_line;
  638.  
  639.     for (i = col; i < oldlen && new[i] != 0; i++)
  640.         if (sline->s_line[i] != new[i])
  641.             break;
  642.     if (new[i] == 0 || i == oldlen)
  643.         return !(new[i] == 0 && i == oldlen);
  644.  
  645.     for (j = i + 1; j < oldlen && new[j]; j++) {
  646.         if (new[j] == sline->s_line[i]) {
  647.             NumSaved = IDcomp(new + j, sline->s_line + i,
  648.                     strlen(new)) + NumSimilar(new + i,
  649.                         sline->s_line + i, j - i);
  650.             if (OkayInsert(NumSaved, j - i)) {
  651.                 InsChar(lineno, i, j - i, new);
  652.                 ignore(IDchar(new, lineno, j));
  653.                 return 1;    /* Difference */
  654.             }
  655.         }
  656.     }
  657.  
  658.     for (j = i + 1; j < oldlen && new[i]; j++) {
  659.         if (new[i] == sline->s_line[j]) {
  660.             NumSaved = IDcomp(new + i, sline->s_line + j,
  661.                     oldlen - j);
  662.             if (OkayDelete(NumSaved, j - i, new[oldlen] == 0)) {
  663.                 DelChar(lineno, i, j - i);
  664.                 ignore(IDchar(new, lineno, j));
  665.                 return 1;
  666.             }
  667.         }
  668.     }
  669.     return 1;
  670. }
  671.  
  672. NumSimilar(s, t, n)
  673. register char    *s,
  674.         *t;
  675. {
  676.     register int    num = 0;
  677.  
  678.     while (n--)
  679.         if (*s++ == *t++)
  680.             num++;
  681.     return num;
  682. }
  683.  
  684. IDcomp(s, t, len)
  685. register char    *s,
  686.         *t;
  687. {
  688.     register int    i;
  689.     int    num = 0,
  690.         nonspace = 0;
  691.     char    c;
  692.  
  693.     for (i = 0; i < len; i++) {
  694.         if ((c = *s++) != *t++)
  695.             break;
  696.         if (c != ' ')
  697.             nonspace++;
  698.         if (nonspace)
  699.             num++;
  700.     }
  701.  
  702.     return num;
  703. }
  704.  
  705. OkayDelete(Saved, num, samelength)
  706. {
  707.     static int    DelIn = 0,
  708.             CElen = 0;
  709.  
  710.     if (DelIn == 0) {
  711.         DelIn = weight(DELETE);
  712.         CElen = weight(CLREOL);
  713.     }
  714.  
  715.     /* If the old and the new are the same length, then we don't
  716.      * have to clear to end of line.  We take that into consideration.
  717.      */
  718.     return ((Saved + (!samelength ? CElen : 0)) > (DelIn * num));
  719. }
  720.  
  721. OkayInsert(Saved, num)
  722. {
  723.     int    n;
  724.  
  725.     if (hasIM) {    /* Good terminal.  Fewer characters in this case */
  726.         static int    InsIn = 0;
  727.  
  728.         if (InsIn == 0)
  729.             InsIn = weight(INSERT);
  730.  
  731.         if (InMode)    /* We are already in insert mode */
  732.             n = num;
  733.         else
  734.             n = num + InsIn;
  735.     } else {
  736.         static int    IClen = 0;
  737.  
  738.         if (IClen == 0)
  739.             IClen = weight(INSERTCH);
  740.         n = 2 * num * IClen;
  741.     }
  742.     return Saved > n;
  743. }
  744.  
  745.  
  746. DelChar(lineno, col, num)
  747. {
  748.     register int    i;
  749.  
  750.     Placur(lineno, col);
  751.     for (i = 0; i < num; i++)
  752.         del_chr();
  753.     CopyTo(Screen[lineno].s_line + col, Screen[lineno].s_line + col + num,
  754.             Screen[lineno].s_length);
  755.     Screen[lineno].s_length -= num;
  756. }
  757.  
  758. InsChar(lineno, col, num, new)
  759. char    *new;
  760. {
  761.     register char    *sp1,
  762.             *sp2,    /* To push over the array */
  763.             *sp3;    /* Last character to push over */
  764.  
  765.     int    WithSpaces = !(hasIM);
  766.         /* If no insert mode then the IC inserts spaces
  767.          * for us, and the screen image has to reflect
  768.          * that.
  769.          */
  770.     int    i;
  771.  
  772.     i_set(lineno, 0);
  773.     sp2 = Curline->s_length + num;
  774.     if (sp2 >= cursend) {
  775.         i_set(lineno, CO - (sp2 - cursend) - 1);
  776.         cl_eol();
  777.         sp2 = cursend - 1;
  778.     }
  779.     Curline->s_length = sp2;
  780.     sp1 = sp2 - num;
  781.     sp3 = Curline->s_line + col;
  782.  
  783.     while (sp1 >= sp3)
  784.         *sp2-- = *sp1--;
  785.     sp1 = Curline->s_line + col;
  786.     new += col;
  787.     for (i = 0; i < num; i++)
  788.         *sp1++ = (WithSpaces) ? ' ' : new[i];
  789.     /* The internal screen is correct, and now we have to do
  790.      * the physical stuff
  791.      */
  792.  
  793.     Placur(lineno, col);
  794.     if (!WithSpaces) {
  795.         if (!InMode) {
  796.             ins_mode();
  797.             InMode++;
  798.         }
  799. #ifdef UNIX
  800.         for (i = 0; i < num; i++) {
  801.             outchar(new[i]);
  802.             CapCol++;
  803.         }
  804. #else
  805.         writechars(new,new +num -1);
  806. #endif
  807.     } else {
  808.          ins_mode();
  809.         for (i = 0; i < num; i++) {
  810.             outchar(' ');
  811.             CapCol++;
  812.         }
  813.         ex_ins_mode();
  814.     }
  815. }
  816.  
  817.  
  818. /*-----------------------o.s. dependent-------------------------*/
  819. /* end */
  820.